How To Make A Web Accessible Disclosure Toggle Using Shortcodes

I spoke previously about how to make Divi's toggle module web accessible, but what if you weren't using Divi?

I needed to have a disclosure pattern toggle independent of any theme. It needed to be setup using a shortcode with customizable content.

Ideally, you'd want to wrap this into a plugin, but I'm going to build it inside of a child theme for this tutorial. See the tutorial on child themes if you need a refresher.

How to make a web accessible disclosure toggle: In functions.php add a shortcode that set the customizable content into a span for the toggle and a div for the content. Add the jQuery to trigger the opening and closing functionality. Add CSS to style.css to display the disclosure indicator and handle the visibility.

The code that goes into functions.php is:

add_shortcode( 'mini_toggle', 'mini_toggle_func' );

function mini_toggle_func( $atts, $content = "" ) {
  $id = !empty( $atts['id'] ) ? $atts['id'] : 'mini-toggle';
  $title = !empty( $atts['title'] ) ? $atts['title'] : 'View more';
  $content_id = $id . '-content';
  $html = "";
  $html .= "<span class='mini-toggle-trigger mini-toggle-closed' role='button' id='$id' aria-controls='$content_id' aria-expanded='false'>$title</span>";
  $html .= "<div class='mini-toggle-content mini-toggle-closed' id='$content_id' aria-labelledby='$id'><p>$content</p></div>";
  $html .="<script>
  jQuery(document).ready(function ($) {
    var toggleClosed = 'mini-toggle-closed';
    var toggleOpen = 'mini-toggle-open';
    $('.mini-toggle-trigger').click(function() {
      var relatedContent = $(this).attr('aria-controls');
      if ($(this).hasClass(toggleClosed)) {
        $(this).removeClass(toggleClosed);
        $(this).addClass(toggleOpen);
        $(this).attr('aria-expanded','true');
        $('#' + relatedContent).removeClass(toggleClosed);
        $('#' + relatedContent).addClass(toggleOpen);
      } else {
        $(this).removeClass(toggleOpen);
        $(this).addClass(toggleClosed);
        $(this).attr('aria-expanded','false');
        $('#' + relatedContent).removeClass(toggleOpen);
        $('#' + relatedContent).addClass(toggleClosed);
      }
    });
  });
  </script>";
  return $html;
}

Then add this to style.css or to Additional CSS in the Theme Customizer:

.mini-toggle-closed.mini-toggle-content {
  display: none;
}
.mini-toggle-open.mini-toggle-content {
  display: block;
}
.mini-toggle-closed.mini-toggle-trigger::before {
  font-family: "FontAwesome";
  content: "\f054";
}
.mini-toggle-open.mini-toggle-trigger::before {
  font-family: "FontAwesome";
  content: "\f078";
}

For the disclosure indicators, I'm using Font Awesome with the free Font Awesome Plugin. You can just install and activate that and be up and running.

If you're using a different font set to display the disclosure indicators, or your theme already has Font Awesome, you might need to adjust the name of the font-family or the content to match.

How to use the shortcode

To use this shortcode, add the following to your page, post or widget:

[mini_toggle id="toggle1" title="See more about us"]This is the content about us.[/mini_toggle]

The order of the id and title don't matter.

If you only have one disclosure toggle on a page, you don't need to add the id. But if you are going to have multiple disclosure toggles, you need to add a unique id to each one. You can use digits, just not as the first character of the id.

The title will become the title of the button that triggers the visibility.

The part between the square brackets is the content that will be hidden initially and become visible when someone clicks on it.

The outputted code looks like this:

<span class="mini-toggle-trigger mini-toggle-closed" role="button" id="toggle1" aria-controls="toggle1-content" aria-expanded="false">See more about us</span>
<div class="mini-toggle-content mini-toggle-closed" id="toggle1-content" aria-labelledby="toggle1">
  <p>This is the content about us.</p>
</div>

How to use the code for multiple toggles on a page

If you're going to use multiple toggles on a page, then you should pull in the jQuery separately. Otherwise it will be outputted as many times as you have shortcodes and may cause issues.

Instead of the previous, add this code to functions.php:

add_shortcode( 'mini_toggle', 'mini_toggle_func' );

function mini_toggle_func( $atts, $content = "" ) {
  $id = !empty( $atts['id'] ) ? $atts['id'] : 'mini-toggle';
  $title = !empty( $atts['title'] ) ? $atts['title'] : 'View more';
  $content_id = $id . '-content';
  $html = "";
  $html .= "<span class='mini-toggle-trigger mini-toggle-closed' role='button' id='$id' aria-controls='$content_id' aria-expanded='false'>$title</span>";
  $html .= "<div class='mini-toggle-content mini-toggle-closed' id='$content_id' aria-labelledby='$id'><p>$content</p></div>";
  return $html;
}

Then you'll need to add the jQuery separately.

If you're going to be using the toggles on multiple pages, add the jQuery to an external file called from your functions.php file. Otherwise it's fine to paste it into the page through your page builder or using something like SOGO Header Footer Scripts.

This is the jQuery you'll need:

<script>
jQuery(document).ready(function ($) {
  var toggleClosed = 'mini-toggle-closed';
  var toggleOpen = 'mini-toggle-open';
  $('.mini-toggle-trigger').click(function() {
    var relatedContent = $(this).attr('aria-controls');
    if ($(this).hasClass(toggleClosed)) {
      $(this).removeClass(toggleClosed);
      $(this).addClass(toggleOpen);
      $(this).attr('aria-expanded','true');
      $('#' + relatedContent).removeClass(toggleClosed);
      $('#' + relatedContent).addClass(toggleOpen);
    } else {
      $(this).removeClass(toggleOpen);
      $(this).addClass(toggleClosed);
      $(this).attr('aria-expanded','false');
      $('#' + relatedContent).removeClass(toggleOpen);
      $('#' + relatedContent).addClass(toggleClosed);
    }
  });
});
</script>

Because this code pulls in the ID of the clicked toggle (the var relatedContent line), it can be used with multiple toggles on the same page.

Leave a Comment