Accordion Menus

Single Section Open Demo

This is a plain text section

“When King Lear dies in Act V, do you know what Shakespeare has written? He’s written “He dies.” That’s all, nothing more. No fanfare, no metaphor, no brilliant final words. The culmination of the most influential work of dramatic literature is “He dies.” It takes Shakespeare, a genius, to come up with “He dies.” And yet every time I read those two words, I find myself overwhelmed with dysphoria. And I know it’s only natural to be sad, but not because of the words “He dies,” but because of the life we saw prior to the words. I’ve lived all five of my acts, Mahoney, and I am not asking you to be happy that I must go. I’m only asking that you turn the page, continue reading… and let the next story begin. And if anyone asks what became of me, you relate my life in all its wonder, and end it with a simple and modest “He died.”

This is a plain text section with an image

“Now, a staple of the superhero mythology is, there’s the superhero and there’s the alter ego. Batman is actually Bruce Wayne, Spider-Man is actually Peter Parker. When that character wakes up in the morning, he’s Peter Parker. He has to put on a costume to become Spider-Man. And it is in that characteristic Superman stands alone.”

This is a form section
This is a plain text section

“When King Lear dies in Act V, do you know what Shakespeare has written? He’s written “He dies.” That’s all, nothing more. No fanfare, no metaphor, no brilliant final words. The culmination of the most influential work of dramatic literature is “He dies.” It takes Shakespeare, a genius, to come up with “He dies.” And yet every time I read those two words, I find myself overwhelmed with dysphoria. And I know it’s only natural to be sad, but not because of the words “He dies,” but because of the life we saw prior to the words. I’ve lived all five of my acts, Mahoney, and I am not asking you to be happy that I must go. I’m only asking that you turn the page, continue reading… and let the next story begin. And if anyone asks what became of me, you relate my life in all its wonder, and end it with a simple and modest “He died.”

				
					
<body>
    <!-- We wrap the entirety of the accordion with a DIV wrapper to apply component wide styles should be want/need to do that-->
    <div id="accordionGroup" class="accordionMain">
      <!-- Similarly, each accordion section will be wrapped within it's own wrapper -->
      <div class="accordion-section-wrapper">
        <!-- A button element is being used because it handles the ARIA-EXPANDED attribute, is naturally in the tab order, and can easily be targeted with CSS -->
        <!-- We've applied a class attribute of "accordion-trigger" which we will ultimately use in our Javascript as a target to apply event listeners on programmatically -->
        <!-- The ARIA-EXPANDED attribute of each button will dynamically be changed based on the state of each accordion section -->
        <button aria-expanded="false" class="accordion-trigger" id="accordion-head-one">
          Accordion Section One
          <img decoding="async" class="accordion-icon" src="https://www.flaticon.com/svg/vstatic/svg/709/709586.svg?token=exp=1620073251~hmac=23506a86ff515412bbe689d82029428e" alt="">
        </button>
        <!-- The content of the accordion section is held within a DIV element and an accordion section class that will be targeted to handle the show/hide functionality -->
        <div id="accordion-section-one" class="accordion-content-section">
          <!-- The first element in each accordion is a heading element, providing context to the content within -->
          <h5>This is a plain text section</h5>
          <p>
            “When King Lear dies in Act V, do you know what Shakespeare has
            written? He’s written “He dies.” That’s all, nothing more. No
            fanfare, no metaphor, no brilliant final words. The culmination of
            the most influential work of dramatic literature is “He dies.” It
            takes Shakespeare, a genius, to come up with “He dies.” And yet
            every time I read those two words, I find myself overwhelmed with
            dysphoria. And I know it’s only natural to be sad, but not because
            of the words “He dies,” but because of the life we saw prior to the
            words. I’ve lived all five of my acts, Mahoney, and I am not asking
            you to be happy that I must go. I’m only asking that you turn the
            page, continue reading… and let the next story begin. And if anyone
            asks what became of me, you relate my life in all its wonder, and
            end it with a simple and modest “He died.”
          </p>
        </div>
      </div>

      <div class="accordion-section-wrapper">
        <button aria-expanded="false" class="accordion-trigger" id="accordion-head-two">
          Accordion Section Two
          <img decoding="async" class="accordion-icon" src="https://www.flaticon.com/svg/vstatic/svg/709/709586.svg?token=exp=1620073251~hmac=23506a86ff515412bbe689d82029428e" alt="">
        </button>
        <div id="accordion-section-two" class="accordion-content-section">
          <div class="imageAccordionSection">
            <h5>This is a plain text section with an image</h5>
            <img decoding="async" src="https://images.unsplash.com/photo-1569003339405-ea396a5a8a90?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80" alt="">
        </div>
          <p>
            “Now, a staple of the superhero mythology is, there’s the superhero
            and there’s the alter ego. Batman is actually Bruce Wayne,
            Spider-Man is actually Peter Parker. When that character wakes up in
            the morning, he’s Peter Parker. He has to put on a costume to become
            Spider-Man. And it is in that characteristic Superman stands alone.”
          </p>
        </div>
      </div>

      <div class="accordion-section-wrapper">
        <button aria-expanded="false" class="accordion-trigger" id="accordion-head-three">
          Accordion Section Three
          <img decoding="async" class="accordion-icon" src="https://www.flaticon.com/svg/vstatic/svg/709/709586.svg?token=exp=1620073251~hmac=23506a86ff515412bbe689d82029428e" alt="">
        </button>
        <div id="accordion-section-three" class="accordion-content-section">
          <h5>This is a form section</h5>
          <div class="formAccordionSection">
            <form>
              <div>
                <label for="search">Search:</label> <input type="text" name="search" id="search" placeholder="e.g. Apple Pie">
              </div>
              <div>
                <label for="email">Email: </label> <input type="text" name="email" id="email" placeholder="joe@example.com">
              </div>
              <div>
                <label for="submit"> <input type="submit" name="submit" id="submit"></label>
              </div>
            </form>
          </div>
        </div>
      </div>

      <div class="accordion-section-wrapper">
        <button aria-expanded="false" class="accordion-trigger" id="accordion-head-four">
          Accordion Section Four
          <img decoding="async" class="accordion-icon" src="https://www.flaticon.com/svg/vstatic/svg/709/709586.svg?token=exp=1620073251~hmac=23506a86ff515412bbe689d82029428e" alt="">
        </button>
        <div id="accordion-section-four" class="accordion-content-section">
          <h5>This is a plain text section</h5>
          <p>
            “When King Lear dies in Act V, do you know what Shakespeare has
            written? He’s written “He dies.” That’s all, nothing more. No
            fanfare, no metaphor, no brilliant final words. The culmination of
            the most influential work of dramatic literature is “He dies.” It
            takes Shakespeare, a genius, to come up with “He dies.” And yet
            every time I read those two words, I find myself overwhelmed with
            dysphoria. And I know it’s only natural to be sad, but not because
            of the words “He dies,” but because of the life we saw prior to the
            words. I’ve lived all five of my acts, Mahoney, and I am not asking
            you to be happy that I must go. I’m only asking that you turn the
            page, continue reading… and let the next story begin. And if anyone
            asks what became of me, you relate my life in all its wonder, and
            end it with a simple and modest “He died.”
          </p>
        </div>
      </div>
    </div>

    <script src="logic.js"></script>
  </body>
				
			
				
					
/*  targeting the wrapper of each accordion section to handle the flex display and formatting */
.accordion-section-wrapper {
  width: 45%;
  margin: auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  }

/*  simple formatting to retain image quality responsively within a content section */
.accordion-content-section img {
  width: 50%;
  height: auto;
  margin:1rem;
}

/*  simple formatting for our heading elements in each accordion section */
.accordion-section-wrapper h5 {
  font-size: 1.2em;
  width: 40%;
}

/*  removing the border (NOTE: NOT removing the OUTLINE which focus indicators inherit their style from) and stylizing the buttons a little bit for a cleaner look */
.accordion-section-wrapper button {
  cursor: pointer;
  height: 3em;
  font-size: 1em;
  color: #c80a00;
  background-color: white;
  border: none;
  border-bottom: grey 1px solid;
}

/*  we set the default nature of the accordions to display:none, or collapsed, and wait to apply a class that will override this style */
/*  the content has also been formatted slightly */
.accordion-content-section {
  display: none;
  width: 80%;
  margin: auto;
}

/*  any accordion section with an open class will result in that accordion section getting this style, which overrides the display:none default */
.open {
  display: block;
}

/*  extra base styling for an image accordion section */
.imageAccordionSection {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
}

/*  extra base styling for a form accordion section */
.formAccordionSection {
  margin: auto;
  display: flex;
  width: 60%;
  justify-content: center;
}

/*  base styling for icon */
.accordion-icon {
  width: 10px;
  height: auto;
  margin-left: 2em;
}
				
			
				
					
/*  we start by programmatically grabbing every trigger for the accordion sections and running a function once on every item with forEach*/
/*  it should be noted that this is programmatic and will dynamically be applied to any dynamically added sections not on initial render*/
document.querySelectorAll(".accordion-trigger").forEach((item) => {
  /*  here we add an event listener to every accordion trigger, in this case all the buttons with that associated class */
  item.addEventListener("click", function (event) {
    /*  we are going to save a bunch of element arrays into variables to clean up the code moving forward and give us easy access to programmatic state changes */
    /* 
      1. we have put every trigger element into an array allAccordionTriggers
      2. we have put every accordion content section (the sections being collapsed/expanded) into an array allAccordion
      3. we have targeted the section that we want to collapse/expand by grabbing the target of the click event (the button), moving to it's parent element which is the 
          section wrapper DIV, and searching for the class "accordion-content-section" which gives us the target we need for state changes recursively
    */ 
    let allAccordionTriggers = document.querySelectorAll(".accordion-trigger");
    let allAccordions = document.querySelectorAll(".accordion-content-section");
    let accordionSectionofClick = event.target.parentNode.querySelector(
      ".accordion-content-section"
    );
    let allAccordionIcons = document.querySelectorAll(".accordion-icon");
    /*  we are going to run a few logic statements*/
    /*  first, we check if the accordion section interacted with is closed */
    if (accordionSectionofClick.classList.contains("open") === false) {
      /*  if it is, we run a forEach on every accordion section in the allAccordions array */
      allAccordions.forEach((item) => {
        /*  we remove the open class from every accordion ensuring that every other section is closed */
        item.classList.remove("open");
        /*  handle the icon rotation*/
      event.target.parentNode.querySelector(".accordion-icon").style.transform = "rotate(0deg)";
      });
    /*  we run a forEach on every button trigger to handle ARIA-EXPANDED */
    allAccordionTriggers.forEach((item) => {
      /* since every accordion just got closed, we set every trigger's ARIA-EXPANDED attribute to false to reflect that state change */
      item.setAttribute("aria-expanded", "false");
    })
    allAccordionIcons.forEach((item) => {
      /* since every accordion just got closed, we set every icon to rotate to reflect that state change */
      item.style.transform = "rotate(0deg)";
    })
    /* here we grab the accordion section that we want to expand and toggle a class on it which will override the default display */
    accordionSectionofClick.classList.toggle("open");
    /* apply the correct state change to ARIA-EXPANDED on the trigger */
    event.target.setAttribute("aria-expanded", "true");
    /*  handle the icon rotation*/
    event.target.parentNode.querySelector(".accordion-icon").style.transform = "rotate(90deg)";
    /* now, if the accordion section that was interacted with is currently open */
    } else {
      /* we will toggle the open class on the accordion section so that it collapses */
      accordionSectionofClick.classList.toggle("open");
      /* update the ARIA-EXPANDED attribute to reflect the state change */
      event.target.setAttribute("aria-expanded", "false");
      /*  handle the icon rotation*/
    event.target.parentNode.querySelector(".accordion-icon").style.transform = "rotate(0deg)";
    }
  });
});
				
			

Multiple Sections Open Demo

This is a plain text section

“When King Lear dies in Act V, do you know what Shakespeare has written? He’s written “He dies.” That’s all, nothing more. No fanfare, no metaphor, no brilliant final words. The culmination of the most influential work of dramatic literature is “He dies.” It takes Shakespeare, a genius, to come up with “He dies.” And yet every time I read those two words, I find myself overwhelmed with dysphoria. And I know it’s only natural to be sad, but not because of the words “He dies,” but because of the life we saw prior to the words. I’ve lived all five of my acts, Mahoney, and I am not asking you to be happy that I must go. I’m only asking that you turn the page, continue reading… and let the next story begin. And if anyone asks what became of me, you relate my life in all its wonder, and end it with a simple and modest “He died.”

This is a plain text section

“When King Lear dies in Act V, do you know what Shakespeare has written? He’s written “He dies.” That’s all, nothing more. No fanfare, no metaphor, no brilliant final words. The culmination of the most influential work of dramatic literature is “He dies.” It takes Shakespeare, a genius, to come up with “He dies.” And yet every time I read those two words, I find myself overwhelmed with dysphoria. And I know it’s only natural to be sad, but not because of the words “He dies,” but because of the life we saw prior to the words. I’ve lived all five of my acts, Mahoney, and I am not asking you to be happy that I must go. I’m only asking that you turn the page, continue reading… and let the next story begin. And if anyone asks what became of me, you relate my life in all its wonder, and end it with a simple and modest “He died.”

This is a plain text section

“When King Lear dies in Act V, do you know what Shakespeare has written? He’s written “He dies.” That’s all, nothing more. No fanfare, no metaphor, no brilliant final words. The culmination of the most influential work of dramatic literature is “He dies.” It takes Shakespeare, a genius, to come up with “He dies.” And yet every time I read those two words, I find myself overwhelmed with dysphoria. And I know it’s only natural to be sad, but not because of the words “He dies,” but because of the life we saw prior to the words. I’ve lived all five of my acts, Mahoney, and I am not asking you to be happy that I must go. I’m only asking that you turn the page, continue reading… and let the next story begin. And if anyone asks what became of me, you relate my life in all its wonder, and end it with a simple and modest “He died.”

				
					
<body>
    <div id="accordionGroup" class="accordionMain">
        <div class="accordion-section-wrapper">
            <button aria-expanded="false" class="accordion-trigger" id="accordion-head-one">
                Accordion Section One
                <img decoding="async" class="accordion-icon" src="https://www.flaticon.com/svg/vstatic/svg/709/709586.svg?token=exp=1620073251~hmac=23506a86ff515412bbe689d82029428e" alt="">
            </button>
            
            <div id="accordion-section-one" class="accordion-content-section">
                <h5>This is a plain text section</h5>
                <p>“When King Lear dies in Act V, do you know what Shakespeare has written? He’s written “He dies.”
                    That’s all, nothing more. No fanfare, no metaphor, no brilliant final words. The culmination of the
                    most influential work of dramatic literature is “He dies.” It takes Shakespeare, a genius, to come
                    up with “He dies.” And yet every time I read those two words, I find myself overwhelmed with
                    dysphoria. And I know it’s only natural to be sad, but not because of the words “He dies,” but
                    because of the life we saw prior to the words. I’ve lived all five of my acts, Mahoney, and I am not
                    asking you to be happy that I must go. I’m only asking that you turn the page, continue reading… and
                    let the next story begin. And if anyone asks what became of me, you relate my life in all its
                    wonder, and end it with a simple and modest “He died.”</p>
            </div>
        </div>

        <div class="accordion-section-wrapper">
            <button aria-expanded="false" class="accordion-trigger" id="accordion-head-two">
                Accordion Section Two
                <img decoding="async" class="accordion-icon" src="https://www.flaticon.com/svg/vstatic/svg/709/709586.svg?token=exp=1620073251~hmac=23506a86ff515412bbe689d82029428e" alt="">
            </button>
            <div id="accordion-section-two" class="accordion-content-section">
                <h5>This is a plain text section</h5>
                <p>“When King Lear dies in Act V, do you know what Shakespeare has written? He’s written “He dies.”
                    That’s all, nothing more. No fanfare, no metaphor, no brilliant final words. The culmination of the
                    most influential work of dramatic literature is “He dies.” It takes Shakespeare, a genius, to come
                    up with “He dies.” And yet every time I read those two words, I find myself overwhelmed with
                    dysphoria. And I know it’s only natural to be sad, but not because of the words “He dies,” but
                    because of the life we saw prior to the words. I’ve lived all five of my acts, Mahoney, and I am not
                    asking you to be happy that I must go. I’m only asking that you turn the page, continue reading… and
                    let the next story begin. And if anyone asks what became of me, you relate my life in all its
                    wonder, and end it with a simple and modest “He died.”</p>
            </div>
        </div>

        <div class="accordion-section-wrapper">
            <button aria-expanded="false" class="accordion-trigger" id="accordion-head-three">
                Accordion Section Three
                <img decoding="async" class="accordion-icon" src="https://www.flaticon.com/svg/vstatic/svg/709/709586.svg?token=exp=1620073251~hmac=23506a86ff515412bbe689d82029428e" alt="">
            </button>
            <div id="accordion-section-two" class="accordion-content-section">
                <h5>This is a plain text section</h5>
                <p>“When King Lear dies in Act V, do you know what Shakespeare has written? He’s written “He dies.”
                    That’s all, nothing more. No fanfare, no metaphor, no brilliant final words. The culmination of the
                    most influential work of dramatic literature is “He dies.” It takes Shakespeare, a genius, to come
                    up with “He dies.” And yet every time I read those two words, I find myself overwhelmed with
                    dysphoria. And I know it’s only natural to be sad, but not because of the words “He dies,” but
                    because of the life we saw prior to the words. I’ve lived all five of my acts, Mahoney, and I am not
                    asking you to be happy that I must go. I’m only asking that you turn the page, continue reading… and
                    let the next story begin. And if anyone asks what became of me, you relate my life in all its
                    wonder, and end it with a simple and modest “He died.”</p>
            </div>
        </div>
    </div>

    <script src="logic.js"></script>
</body>
				
			
				
					
/* base stylings for full accordion sections */
.accordion-section-wrapper {
    max-width: 45%;
    width: 45%;;
    margin: auto;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}

/*  just making the heading text a little bigger */
.accordion-section-wrapper h5 {
    font-size: 1.2em;
}

/*  styling the buttons to be more clean and minimal 
    NOTE: the border style has been changed and not the OUTLINE style which focus indicators inherit from*/
.accordion-section-wrapper button {
    cursor: pointer;
    height: 3em;
    font-size: 1em;
    color: #C80A00;
    background-color: white;
    border: none;
    border-bottom: grey 1px solid;
}

/*  content section specific styles */
.accordion-content-section {
    display: none;
    width: 80%;
    margin: auto;
}

/* css class to toggle */
.open {
    display: block;
}

/*  base icon styles */
.accordion-icon {
    width: 10px;
    height: auto;
    margin-left: 2em;
}
				
			
				
					
/*  we start by grabbing all of the trigger elements, in this case every button with this trigger class on it */
document.querySelectorAll(".accordion-trigger").forEach(item => {
    /*  we will run a forEach function on the array produced above and add event listeners to every single button trigger */
    item.addEventListener("click", function(event) {
        /*  here we save the target accordion section to collapse/expand by grabbing the button trigger, moving up to it's parent (the wrapper DIV) and searching for a specific class 
             which will yield the target section we were looking for */
        let targetNode = event.target.parentNode.querySelector(".accordion-content-section");
        /*  here we just check if the section is already open or not, and if it is not open we run some Javascript*/
        if (targetNode.classList.contains("open") === false) {
            /*  first we will toggle the open class on the accordion section, resulting in the accordion section expanding */
        targetNode.classList.toggle("open");
        /*  second we will handle the ARIA-EXPANDED attribute to properly communicate the current state of the section */
        event.target.setAttribute("aria-expanded", "true");
        /*  handle the icon rotation */
        event.target.parentNode.querySelector(".accordion-icon").style.transform = "rotate(90deg)";
        /*  if the targeted section is currently open we will run some Javascript */
        } else {
            /*  we will start by toggling the open class again to collapse the section*/
            targetNode.classList.toggle("open")
            /*  then we will handle the ARIA-EXPANDED state to communicate the updated state of the section */
            event.target.setAttribute("aria-expanded", "false");
            /*  handle the icon rotation */
            event.target.parentNode.querySelector(".accordion-icon").style.transform = "rotate(0deg)";
        }
    });
});
				
			

Why use an accordion?

Accordions are a great component to use in situations when you have a large amount of content that you would like to hide until a user decides to reveal that content. Accordions are versatile. They share similarities with anchor links, helping users navigate through page content. They also can be used to organize information in a logical manner

What are some accessibility concerns?

  1. Keyboard Navigation:
    • Ensure that all accordion elements are keyboard navigable. Users should be able to open and close sections using keyboard inputs, like the Tab key, Enter key, and arrow keys.
  2. Focus Management:
    • Manage focus properly when an accordion section is opened. Set focus to the first focusable element within the expanded section and ensure it’s visually indicated.
  3. Screen Reader Compatibility:
    • Use semantic HTML elements like <button> and <div> appropriately to ensure screen readers can announce accordion headers and their state correctly.
    • Provide meaningful text within the accordion headers to convey their purpose.
  4. ARIA Roles and Attributes:
    • Use ARIA (Accessible Rich Internet Applications) roles and attributes to enhance accessibility. For example, use aria-expanded to indicate the open/closed state of an accordion section.
  5. Skip Links:
    • Consider implementing skip links to allow users to bypass repeated accordion sections and go directly to the content they’re interested in.
  6. Visual and Auditory Cues:
    • Provide clear visual cues (such as icons or text) to indicate the open or closed state of accordion sections.
Tested using
Chrome
with NVDA
Firefox
with NVDA
  • W3C SVG
    1.3.1
    Info and Relationships ( level A ) :
    Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text.
  • W3C SVG
    2.1.1
    Keyboard ( level A ) :
    All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes, except where the underlying function requires input that depends on the path of the user's movement and not just the endpoints.
  • W3C SVG
    4.1.2
    Name, Role, Value ( level A ) :
    For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies.