Accordions

An accordion menu is a vertically stacked list of headers that can be clicked to hide or show the content within.

Best practices

  • Accordions are not a one-size-fits-all solution and should be used carefully. Scrolling is an acceptable behaviour when content is relevant and organized properly. In most cases, it’s better to display all content by default.
  • The above applies when considering nested accordions, which should be avoided in favour of displaying content, features, and functionality on screen.
  • Consider using accordions when you have a lot of information that might not be useful for all users.
  • Accordions should not be used when the information is of high importance as users could have trouble finding what they need. Content within accordions might not be visible, or given as much weight as visible content, to search engines. A site’s most important content should be visible by default. Google is able to crawl HTML content hidden inside navigational elements such as tabs or expanding sections, however this content is less accessible to users.
  • Accordion section labels should describe the content within and be aligned with user goals.

How it works

The Bootstrap Collapse JavaScript plugin is used to show and hide content. Buttons or anchors are used as triggers that are mapped to specific elements you toggle. Collapsing an element will animate the height from its current value to 0. Given how CSS handles animations, you cannot use padding on a .collapse element. Instead, use the class as an independent wrapping element.

The animation effect of this component is dependent on the prefers-reduced-motion media query. See Bootstrap’s reduced motion section of our accessibility documentation.

Using the Bootstrap card component, you can extend the default collapse behaviour to create an accordion. To properly achieve the accordion style, be sure to use .accordion as a wrapper.

Collapsible Group Item #1

Etiam vitae imperdiet nisi, in auctor ipsum. Nulla tempor felis at lectus tempus, a dignissim mauris pretium. In aliquet imperdiet dui, eget suscipit metus aliquam sed. Nam est ipsum, pharetra ac turpis nec, molestie fermentum metus. Suspendisse commodo egestas ligula eu venenatis.

Fusce eu risus quam. Vestibulum varius varius cursus. Suspendisse ut ante suscipit, ornare urna eu, vestibulum sapien. Sed pulvinar facilisis odio quis semper. Integer tempor finibus dignissim. Proin neque quam, commodo ac hendrerit at, fringilla sodales ligula. In id elit at lectus efficitur luctus nec at leo. Nulla orci urna, egestas sit amet urna sit amet, tempus posuere dui.

Donec eu arcu a risus fringilla fringilla eu eu neque. Ut pretium commodo gravida. Etiam vehicula erat at massa fermentum, eu tristique leo condimentum. Quisque quis ligula lobortis, maximus tellus eget, volutpat turpis. Nullam nunc diam, porta vitae consectetur in, efficitur in metus.

<div class="text-right pt-2 pb-2">
  <button type="button" class="btn btn-link p-0 mr-2 expandAll" data-target="#accordionExample">Expand all</button>
  <button type="button" class="btn btn-link p-0 collapseAll" data-target="#accordionExample">Collapse all</button>
</div>

<div class="accordion" id="accordionExample">
  <div class="card">
    <div class="card-header" id="headingOne">
      <div class="heading" role="button" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
        Collapsible Group Item #1
        <i class="far fa-chevron-up"></i>
      </div>
    </div>
    <div id="collapseOne" class="collapse show" aria-labelledby="headingOne">
      <div class="card-body">
        <p>Etiam vitae <a href="#">imperdiet nisi</a>, in auctor ipsum. Nulla tempor felis at lectus tempus, a dignissim mauris pretium. In aliquet imperdiet dui, eget suscipit metus aliquam sed. Nam est ipsum, pharetra ac turpis nec, molestie fermentum metus. Suspendisse commodo egestas ligula eu venenatis.</p>
      </div>
    </div>
  </div>
  <div class="card">
    <div class="card-header" id="headingTwo">
      <div class="heading" role="button" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
        Collapsible Group Item #2
        <i class="far fa-chevron-down"></i>
      </div>
    </div>
    <div id="collapseTwo" class="collapse" aria-labelledby="headingTwo">
      <div class="card-body">
        <p>Fusce eu risus quam. Vestibulum varius varius cursus. Suspendisse ut ante suscipit, ornare urna eu, vestibulum sapien. Sed pulvinar facilisis odio quis semper. Integer tempor finibus dignissim. Proin neque quam, commodo ac hendrerit at, fringilla sodales ligula. In id elit at lectus efficitur luctus nec at leo. Nulla orci urna, egestas sit amet urna sit amet, tempus posuere dui.</p>
      </div>
    </div>
  </div>
  <div class="card">
    <div class="card-header" id="headingThree">
      <div class="heading" role="button" data-toggle="collapse" data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
        Collapsible Group Item #3
        <i class="far fa-chevron-down"></i>
      </div>
    </div>
    <div id="collapseThree" class="collapse" aria-labelledby="headingThree">
      <div class="card-body">
        <p>Donec eu arcu a risus fringilla fringilla eu eu neque. Ut pretium commodo gravida. Etiam vehicula erat at massa fermentum, eu tristique leo condimentum. Quisque quis ligula lobortis, maximus tellus eget, volutpat turpis. Nullam nunc diam, porta vitae consectetur in, efficitur in metus.</p>
      </div>
    </div>
  </div>
</div>

Add the custom dropdown icon toggle, and the ‘Expand all’ and ‘Collapse all’ links:

$('.accordion .heading').click(function(){
  // Toggle the icon
  $(this).find('i').toggleClass('fa-chevron-down fa-chevron-up');
})

$('.collapse').on('hidden.bs.collapse', function () {
  // Toggle the icon
  $(this).find('i.fa-chevron-up').toggleClass('fa-chevron-down fa-chevron-up');

  // Disable the expand all link
  var id = $(this).closest('.accordion').attr('id');
  $('.expandAll[data-target="#'+id+'"]').removeClass('disabled');

  // If all items are hidden then disable the collapse link
  if($(this).closest('.accordion').find('.collapse.show').length == 0){
    $('.collapseAll[data-target="#'+id+'"]').addClass('disabled');
  }
})

$('.collapse').on('shown.bs.collapse', function () {
  // Toggle the icon
  $(this).find('i.fa-chevron-down').toggleClass('fa-chevron-down fa-chevron-up');

  // Disable the collapse all link
  var id = $(this).closest('.accordion').attr('id');
  $('.collapseAll[data-target="#'+id+'"]').removeClass('disabled');

  // If all items are shown then disable the expand link
  if($(this).closest('.accordion').find('.collapse:not(.show)').length == 0){
    $('.expandAll[data-target="#'+id+'"]').addClass('disabled');
  }
})

$('.expandAll').click(function(){
  // Disable the expand all link
  var id = $(this).attr('data-target');
  $(this).addClass('disabled');

  // Enable the collapse all link
  $('.collapseAll[data-target="'+id+'"]').removeClass('disabled');

  // Show all items
  $(id + ' .collapse').collapse('show');

  // Toggle the icons
  $(id).find('i.fa-chevron-down').toggleClass('fa-chevron-down fa-chevron-up');
})

$('.collapseAll').click(function(){
  // Disable the collapse all link
  var id = $(this).attr('data-target');
  $(this).addClass('disabled');

  // Enable the expand all link
  $('.expandAll[data-target="'+id+'"]').removeClass('disabled');

  // Hide all items
  $(id + ' .collapse').collapse('hide');

  // Toggle the icons
  $(id).find('i.fa-chevron-up').toggleClass('fa-chevron-down fa-chevron-up');
})

Borderless

Each web property should stick to a single accordion style for consistency. If your project already uses the bordered accordion then do not use the borderless style.

For the border-less version add the class borderless to your accordion.

Collapsible Group Item #1

Curabitur non est at dolor mattis rutrum eget condimentum ipsum. Nulla gravida, sapien non fermentum aliquet, purus tortor feugiat tellus, at auctor eros turpis in massa.

Fusce sagittis hendrerit metus, ac aliquam arcu gravida eu. Mauris lacinia dignissim dui sed dictum. Nullam a dignissim velit, nec finibus elit. Curabitur a diam nec tellus accumsan efficitur. Donec mauris augue, rutrum sit amet dictum at, tincidunt eget ex.

<div class="accordion borderless" id="accordionExample2">
  <div class="card">
    <div class="card-header" id="headingOne2">
      <div class="heading" role="button" data-toggle="collapse" data-target="#collapseOne2" aria-expanded="true" aria-controls="collapseOne2">
        Collapsible Group Item #1
        <i class="far fa-chevron-up"></i>
      </div>
    </div>
    <div id="collapseOne2" class="collapse show" aria-labelledby="headingOne2">
      <div class="card-body">
        <p>Curabitur non est at dolor mattis rutrum eget condimentum ipsum. Nulla gravida, sapien non fermentum aliquet, purus tortor feugiat tellus, at auctor eros turpis in massa.</p>
      </div>
    </div>
  </div>
  <div class="card">
    <div class="card-header" id="headingTwo2">
      <div class="heading" role="button" data-toggle="collapse" data-target="#collapseTwo2" aria-expanded="false" aria-controls="collapseTwo2">
        Collapsible Group Item #2
        <i class="far fa-chevron-down"></i>
      </div>
    </div>
    <div id="collapseTwo2" class="collapse" aria-labelledby="headingTwo2">
      <div class="card-body">
        <p>Fusce sagittis hendrerit metus, ac aliquam arcu gravida eu. Mauris lacinia dignissim dui sed dictum. Nullam a dignissim velit, nec finibus elit. Curabitur a diam nec tellus accumsan efficitur. Donec mauris augue, rutrum sit amet dictum at, tincidunt eget ex.</p>
      </div>
    </div>
  </div>
</div>

Accessibility

Be sure to add aria-expanded to the control element. This attribute explicitly conveys the current state of the collapsible element tied to the control to screen readers and similar assistive technologies. If the collapsible element is closed by default, the attribute on the control element should have a value of aria-expanded="false". If you’ve set the collapsible element to be open by default using the show class, set aria-expanded="true" on the control instead. The plugin will automatically toggle this attribute on the control based on whether or not the collapsible element has been opened or closed (via JavaScript, or because the user triggered another control element also tied to the same collapsible element). If the control element’s HTML element is not a button (e.g., an <a> or <div>), the attribute role="button" should be added to the element.

If your control element is targeting a single collapsible element – i.e. the data-target attribute is pointing to an id selector – you should add the aria-controls attribute to the control element, containing the id of the collapsible element. Modern screen readers and similar assistive technologies make use of this attribute to provide users with additional shortcuts to navigate directly to the collapsible element itself.

Note that Bootstrap’s current implementation does not cover the various keyboard interactions described in the WAI-ARIA Authoring Practices 1.1 accordion pattern - you will need to include these yourself with custom JavaScript.

FAQs

The following code can be used for numbered or non-numbered FAQs on winnpeg.ca:

<div class="text-right pt-2">
	<button type="button" class="btn btn-link p-0 mr-2 expandAll" data-target="#accordionExample">Expand all</button>
	<button type="button" class="btn btn-link p-0 collapseAll" data-target="#accordionExample">Collapse all</button>
</div>	

<div class="accordion" id="accordionExample">
	<!-- for additional questions, copy the following div -->
	<div class="card">
		<div class="card-header">
			<div class="heading">
				<div class="heading-content">
					Insert question here
					<i class="far fa-chevron-down"></i>
				</div>
			</div>
		</div>
		<div class="collapse">
			<div class="card-body">
				Insert answer here
			</div>
		</div>
	</div>
</div>

You must also reference the following javascript just before the closing body tag of your page:

  • <script src="/shared/js/faq-numbered-ds.js"></script> for numbered FAQs
  • <script src="/shared/js/faq-ds.js"></script> for non-numbered FAQs

Usage

The collapse plugin utilizes a few classes to handle the heavy lifting:

  • .collapse hides the content
  • .collapse.show shows the content
  • .collapsing is added when the transition starts, and removed when it finishes

These classes can be found in _transitions.scss.

Via data attributes

Just add data-toggle="collapse" and a data-target to the element to automatically assign control of one or more collapsible elements. The data-target attribute accepts a CSS selector to apply the collapse to. Be sure to add the class collapse to the collapsible element. If you’d like it to default open, add the additional class show.

Via JavaScript

Enable manually with:

$('.collapse').collapse()

Options

Options can be passed via data attributes or JavaScript. For data attributes, append the option name to data-, as in data-parent="".

Name Type Default Description
parent selector | jQuery object | DOM element false If parent is provided, then all collapsible elements under the specified parent will be closed when this collapsible item is shown. (similar to traditional accordion behaviour - this is dependent on the card class). The attribute has to be set on the target collapsible area.
toggle boolean true Toggles the collapsible element on invocation

Methods

Asynchronous methods and transitions

All API methods are asynchronous and start a transition. They return to the caller as soon as the transition is started but before it ends. In addition, a method call on a transitioning component will be ignored.

See Bootstrap’s JavaScript documentation for more information.

.collapse(options)

Activates your content as a collapsible element. Accepts an optional options object.

$('#myCollapsible').collapse({
  toggle: false
})

.collapse('toggle')

Toggles a collapsible element to shown or hidden. Returns to the caller before the collapsible element has actually been shown or hidden (i.e. before the shown.bs.collapse or hidden.bs.collapse event occurs).

.collapse('show')

Shows a collapsible element. Returns to the caller before the collapsible element has actually been shown (i.e. before the shown.bs.collapse event occurs).

.collapse('hide')

Hides a collapsible element. Returns to the caller before the collapsible element has actually been hidden (i.e. before the hidden.bs.collapse event occurs).

.collapse('dispose')

Destroys an element’s collapse.

Events

Bootstrap’s collapse class exposes a few events for hooking into collapse functionality.

Event Type Description
show.bs.collapse This event fires immediately when the show instance method is called.
shown.bs.collapse This event is fired when a collapse element has been made visible to the user (will wait for CSS transitions to complete).
hide.bs.collapse This event is fired immediately when the hide method has been called.
hidden.bs.collapse This event is fired when a collapse element has been hidden from the user (will wait for CSS transitions to complete).
$('#myCollapsible').on('hidden.bs.collapse', function () {
  // do something...
})