An expandable, sometimes called an accordion, is an element that can be hidden / revealed with a sliding transition.


From a purely visual standpoint, all you need is a container of class s-expandable and a child of class s-expandable--content. Toggle the state class is-expanded on the container to collapse / expand the content. Care must be taken to keep the collapsing functionality accessible.

<div class="s-card ws3">
    <button class="s-btn s-btn__filled mb8"
            Show first paragraph
    <div class="s-expandable" id="expandable-example">
        <div class="s-expandable--content"></div>

Lorem ipsum dolor sit amet, ex iudicabit necessitatibus usu, cetero laboramus concludaturque mel no, facilisis posidonium cu cum. Pro ex senserit dissentiunt, imperdiet intellegam at sed, ex pri dicit eruditi convenire. Est harum movet gubergren ei, errem dictas evertitur ea sit, at mei oratio eligendi. Ad vis legere possit, vis ne ipsum democritum appellantur. Nullam ancillae iudicabit his ad.

Accusata reprimique interesset in sea, est graece dictas scriptorem ea. Consul facete mediocritatem quo et. Idque hendrerit theophrastus in vim, eum possit feugiat fastidii id. Idque invenire at quo, accusata salutandi sadipscing et qui. Eos doming adipiscing ea, eu pri debitis indoctum dissentiet. At libris labores adolescens eos, ex nec nobis aeterno.


In the usual case in which you have a button or other clickable element that toggles the expanded state, you can use the built-in s-expandable-control functionality. See the JavaScript introduction for general information on JS in Stacks.

  1. Give the s-expandable an id attribute.
  2. Give your button an aria-controls attribute whose value is the ID from 1.
  3. Give your button an aria-expanded attribute whose value is true or false depending on the initial state of your expandable.
  4. Give your button a data-controller="s-expandable-control" attribute.
  5. If your button is an element that is not focusable by default, be sure to make it keyboard-reachable with tabindex="0"
  6. Give your button is an aria-label attribute that makes it clear that this is a expanding/collapsing control, unless this is already clear from its text content

A common need is for one or more CSS classes to be applied to the expandable control whenever the state is toggled, e.g. to indicate a “selected” state. To achieve this, you can add the data-s-expandable-control-toggle-class attribute. The value should be a space-separated list of CSS classes. These classes will be added to the control whenever it expands the expandable, and removed whenever it collapses it.

See the previous section for an example of all of this.

If you are writing custom CSS to indicate the selected state of the expandable control, consider targetting [aria-controls="true"] instead of creating a new class.

If your expandable control is a checkbox or radio button, then the visibility of the expandable will be synchronized with the radio / checkbox state:

<div class="grid--cell">
    <input class="s-radio" type="radio" name="mood-choice" id="mood-happy"
        aria-controls="mood-happy-text" />
<div class="grid--cell">
    <label class="d-block mb4 s-label fw-normal" for="mood-happy">Happy</label>
    <div class="s-expandable" id="mood-happy-text">
        <p class="s-expandable--content">@Svg.FaceSmile</p> 
What is your mood?


When an s-expandable-control collapses or expands an element, it will fire an event of type s-expandable-control:hide or s-expandable-control:show, respectively. This event is fired synchronously. The event’s target element is the s-expandable-control element, not the expandable itself.