Bubble Help

Helping user with form


Bubble Help is a click-activated flyout. It discloses supplementary or advisory content about an existing onscreen element or region.

Thematically, you can think of bubble help content fulfilling the same role as footnotes in a page.

Bubble help is a composite pattern containing a button and an overlay. The button toggles the visibility of the overlay. The overlay contains the help content.

Working Examples

You can take a look at the Bubble Help pattern in action on our examples site.


We use the following terminology when discussing this pattern.

  • bubble-help
    • the composite pattern as a whole, containing a button and overlay
  • button
    • the button that hosts the overlay
  • overlay
    • the overlay that contains the help content
  • expanded
    • a bubble-help with expanded overlay
  • collapsed
    • a bubble0help with collapsed overlay

Best Practices

Overlay must not be modal. Please consider the dialog pattern for modal behaviour.

Button must not have aria-haspopup attribute. Despite the name of this property, it is actually intended specifically for a Menu.

The bubble-help should remain expanded until explicitly closed by user. This allows user to reference overlay content whilst workingelsewhere on page.

Overlay should be hidden by default.

Overlay content should follow the principals of progressive disclosure. It should reveal the right information, at the right time.

Overlay content should be no more than one or two paragraphs in length. For lengthier content, consider instead using a dialog.

Interaction Design

This section provides the pattern interaction design for keyboard, screen reader & pointing devices.


Button must be keyboard focus-able.

Activating button must toggle the expanded state of the overlay. Keyboard focus should remain on the button.

If overlay contains focusable elements, tab order must flow directly from button to first of those elements.

If the overlay has no focus-able elements, tab order must flow directly to next page control.

Screen Reader

Button purpose must be announced (e.g. 'Help).

Button state must be announced (i.e. expanded or collapsed).

Reading order must flow directly from button to overlay.

Overlay content must be announced after expanded.


Invoking button must toggle the expanded state of the overlay.

Developer Guide 1 - Basic

Our first implementation will get us quickly up and running with the accessibility requirements of bubble help. It is not designed with progressive enhancement in mind. If JavaScript is unavailable or fails to load for any reason, the button will be non-operational.


The goal of our content layer is to add the button and overlay. The structure and DOM positioning of these elements is of utmost importance.

<span id="bubblehelp_0" class="bubblehelp">
  <button class="bubblehelp__button" aria-controls="bubblehelp_0-overlay" aria-expanded="false" aria-label="Help" type="button"></button>
  <span class="bubblehelp__live-region" aria-live="polite">
    <div class="bubblehelp__overlay" id="bubblehelp_0-overlay">
      <!-- overlay content -->

Notice placement of the button directly before the live-region element. This allows natural tab order flow and screen reading order from the button into the overlay.

The live-region property is set to "polite".


The goal of the CSS layer is to hide or show the overlay depending on the aria-expanded state.

.bubblehelp {
  position: relative;
.bubblehelp__overlay {
  display: none;
  position: absolute;
  white-space: nowrap;
  z-index: 1;
.bubblehelp__button[aria-expanded=true] ~ .bubblehelp__live-region .bubblehelp__overlay {
  display: block;

The overlay must have display: none by default. This ensures that screen readers cannot access the overlay content when in a collapsed state.


CSS alone cannot trigger the expanded state, so we require a small amount of Javascript to handle this behaviour:

$('.bubblehelp__button').on('click', function(e) {
  var isExpanded = $(this).attr('aria-expanded') === 'true');

  $(this).attr('aria-expanded', isExpanded ? 'false' : 'true');

Invoking the button will now toggle the aria-expanded state of the button.

Animations are also possible of course, but fall outside the scope of accessibility.

Developer Guide 2 - Progressive Enhancement

Our next implementation follows the Progressive Enhancement strategy. We build in a layered fashion that allows everyone to access the basic content and functionality of a web page.

The bubble help begins as a simple internal hyperlink that jumps to the footnotes section of the page.


The goal of our content layer is to provide related help content for any given page element.

Identify Element or Text

First we identify the page element that requires help content. We will use the "Gregor Samsa" text in the following paragraph:

<p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p>

Create Button

Our help button actually starts it's life as an anchor element. We use an internal link pointing to the section of the page containing our help content (identified by the ID of 'help1'):

<p>One morning, when Gregor Samsa <span class="bubblehelp"><a href="#help1"><sup>[1]</sup></a></span> woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p>

Notice we have also wrapped our anchor in a span element that forms the root of our widget for CSS and JavaScript hooks.

Add Content

We will now add our help content to the base markup. We can think of this help content as being a footnote in the page:

<section aria-labelledby="notes_heading" id="footnotes" role="region">
  <h2 id="notes_heading">Footnotes</h2>
      <div id="help1">
        <p>Gregor Samsa appears to be based upon Kafka himself. As when Kafka suffered from <a href="http://en.wikipedia.org/wiki/Insomnia">insomnia</a>, he feared he was repulsive and a burden to his family, during which time his sister was his caretaker.</p>

Viola! With some simple HTML, our bubble-help is already functional, albeit in a primitive fashion.


The goal of our CSS is to style the anchor to appear more button-like and to present the help content inside of an overlay.

We must also consider that our browser maybe in a non-JavaScript situation and act accordingly. There are some things we can do safely before we are sure that JavaScript is available. Likewise there are some CSS rules we only want to apply after we are sure JavaScript has initialised the widget.

Before JS Initialisation

We can style the anchor with a sprite and hide it's text content like so:

.bubblehelp > a {
  content: '';
  display: inline-block;
  background: url('sprite.png') no-repeat -75px -104px;
  width: 16px;
  height: 16px;
.bubblehelp > a sup {
  display: none;

Note that you could also use font icons or SVG here, that is entirely up to you.

After JS Initialisation

We setup a class that will be used for the overlay:

.bubblehelp--js {
  position: relative;
.bubblehelp--js .bubblehelp__overlay {
  background: white;
  display: none;
  position: absolute;
  z-index: 1;

The important rules to note here are position: absolute and z-index. They allow our content to overlay any other element on the page.

In some situations, you may need to use position: fixed instead. Fixed positioning requires JavaScript to maintain overlay position when scrolling or resizing the window.


The goal of our JavaScript layer is to move the content into a new overlay element. Behaviour must also be added for the anchor element to control the overlay.

Locating the Content

The help content will most likely be positioned at the bottom of the page, far away from the help link.

The href attribute of our source anchor contains an ID reference to the target anchor:

<span class="bubblehelp">
  <a href="#help1"><sup>[1]</sup></a>

We can use the ID attribute to locate the content element:

var $this = $(this),
    $anchor = $this.find('> a'),
    href = $anchor.href,
    contentId = href.substring(href.indexOf('#')+1),
    $content = $('#' + contentId),

Again, remember that we do not dictate that you scrape the content of the bubble help in this fashion. Your content can come from anywhere, it can even be injected with JavaScript after an AJAX call if you wish.

Create Overlay

The content element can be re-purposed into an overlay by applying classname 'bubblehelp__overlay'.


Remember that we created the rules for this class in our previous CSS step.


To make assistive technology aware of the help content when expanded, we can wrap it in a live region:

$liveRegion = $('<span aria-live="polite" role="status" />');

Here we create a new live region element and append our content to it.

IMPORTANT: for VoiceOver to identify changes to the live-region, the live-region element itself must remain in the DOM at all times. Any hide, show, add or remove operation must happen on a child of the live-region, not the live-region itself.

DOM Order

The live-region is positioned directly after the anchor element. This ensures that the screen reader and tab order will naturally flow from button into overlay.


Enhancing the Anchor

We add the following roles, states and properties to the anchor element:

$anchor.attr('role', 'button');
$anchor.attr('aria-label', 'Help');
$anchor.attr('aria-controls', contentId);
$anchor.attr('aria-expanded', 'false');

To understand why these attributes are added, please consult the ARIA Reference section of this page below.

Toggle Button

The button must toggle it's own ARIA expanded state.

Remember that anchor elements do not trigger 'click' events on SPACEBAR key. A spacebar event handler must be added manually.

Useful Plugins

The following jQuery plugins may assist you in creation of Bubble-Help pattern:

ARIA Reference


Informs assistive technology to announce the overlay contents whenever the button changes from collapsed to expanded.


Informs assistive technology that our anchor element now behaves like a button instead of a link.


Provides a more accessible button label for assistive technology, over-riding the inner text of the anchor element.


Informs assistive technology that the button controls the expanded state of the flyout.


Informs assistive technology of the expanded state of the button.


This is different to the way BootStrap 'Popovers' work. Why?

The fundamental difference is that the Bootstrap Popovers get their content from a data attribute, whereas the pattern presented here gets it's content from an actual element. This allows us to more easily place HTML such as hyperlinks & images inside of our popovers and, unlike Bootstrap, the popover content will be fully accessible without JavaScript.

results matching ""

    No results matching ""