EPUB 3 Accessibility Guidelines

Hidden Content

Content should never be hidden by default in EPUBs, as this can make it inaccessible to all readers. Readers should always have the option to determine what content they wish to read after the content has loaded, and regardless of whether the information is targeted to facilitate reading by specific groups.

Avoid using CSS solutions for hiding any type of primary content, as they typically don't work as developers expect:

If content is intended for a specific audience, use the techniques that HTML5 and ARIA make available. Standard hyperlinks to text alternatives, such as transcripts of audio and video tracks, are more broadly usable than hidden content.

There are going to be cases where some content does need to be legitimately hidden, such as when including interactive features and forms.

Ensure that such content is not central to understand the publication, and that progressive enhancement techniques have been followed (i.e., the interactive nature of the content that requires the visibility to change is not an impediment to consuming the publication).

The aria-hidden attribute provides a way to selectively hide visible content from an assistive technology, or expose hidden content. Use this attribute with caution, as toggling content for assistive technologies can have negative effects if not all user groups are taken into consideration.

Examples

Example 1 — Hiding a form result area
<div id="result"
     aria-live="assertive"
     hidden="hidden"/>
Example 2 — Providing scripted control over display

The following sample page provides readers the option to hide code examples if they have a reading system that supports scripting and cookies. By default, the reader is alerted that their system may not support the feature (a failure to display could be because the reader has chosen to disable features, so it's better to let them know the feature exists than remove all traces).

<body onload="showControls()">
   <p>
      This book includes samples in both C#
      and VisualBasic. You can disable one 
      or both languages from being displayed 
      by checking the following options:
   </p>
   
   <div id="code-control">
      Sorry, this functionality is only 
      available when both scripting and 
      cookies are enabled.
   </div>
</body>

The following minimal sample JavaScript shows the different functionality that would be required to make this example work. When the preferences page loads, the control checkboxes are inserted in place of the default message if scripting is enabled (the showControls function).

When the reader changes their preferences by selecting or deselecting an option, the new status is stored in a cookie (the setPreferences function). Storing the preference in a cookie means the loadSettings and renderExamples functions could be called in tandem on each new chapter load to hide any content so that the reader does not have to re-set every time.

A more complete example might provide localized options at the point of each example to re-enable.

<script type="text/javascript">
<![CDATA[

var setting = new Array();
   
/* default state is to enable all examples */
setting['show-cs'] = true;
setting['show-vb'] = true;

/* check if the reading system supports the needed scripting */
setting['scriptEnabled'] = (
  !navigator.epubReadingSystem.hasFeature('dom-manipulation') ||
  !navigator.cookieEnabled
) ? false : true;


function showControls() {

  /* exit if the reading system does not support scripting */
  if (!setting['scriptEnabled']) { return; }
  
  var cntrl = document.getElementById('code-control');
  
  /* delete the default text */
  while (cntrl.hasChildNodes()) {
    cntrl.removeChild(cntrl.firstChild);
  }
  
  /* add the checkbox controls */
  createControl('cs');
  createControl('vb');
  
  /* check if reader already has preferences */
  loadSettings();
  
  /* set the checkbox state */
  document.getElementById('hide-cs').checked = !setting['show-cs'];
  document.getElementById('hide-vb').checked = !setting['show-vb'];
}


function createControl(cid) {

  var label = document.createElement('label');
     label.setAttribute('for', cid+'-chkbox');
  
  var chkbox = document.createElement('input');
     chkbox.setAttribute('type', 'checkbox');
     chkbox.onclick = function () { setPreferences(); };
     chkbox.name = cid + '-chkbox';
     chkbox.id = 'hide-' + cid;
  
  label.appendChild(chkbox);
  
  var hideText = 'Hide all ';
  hideText += (cid == 'cs') ? 'C#' : 'VB';
  hideText += ' examples';
  
  label.appendChild(document.createTextNode(hideText));
  
  document.getElementById('code-control').appendChild(label);
}


function loadSettings() {

  /* exit if the reading system does not support scripting */
  if (!setting['scriptEnabled']) { return; }
  
  if ($.cookie('exampleCodeBook')) {
    /*  grab the display preferences from the cookie */
    var display = $.cookie('exampleCodeBook');
    
    var cs = display.substring(0,display.indexOf(';'));
    var vb = display.substring(display.indexOf(';')+1);
    
    setting['show-cs'] = 
      cs.substring(cs.indexOf('=')+1) == 'true' ? true : false;
    setting['show-vb'] =
      vb.substring(vb.indexOf('=')+1) == 'true' ? true : false;
  }
}


function setPreferences() {
  
  /* get the current checked status */
  setting['show-cs'] = !document.getElementById('hide-cs').checked;
  setting['show-vb'] = !document.getElementById('hide-vb').checked;
  
  /* and set preferences to a cookie using jquery-cookie library */
  $.cookie("exampleCodeBook", "cs="+setting['show-cs']+";vb="+setting['show-vb']);

}


function renderExamples() {

  /* exit if the reading system does not support scripting */
  if (!setting['scriptEnabled']) { return; }
  
  var snippets = document.getElementsByTagName('pre');
  
  for (var i = 0; i < snippets.length; i++) {
    if (snippets[i].id.indexOf('-cs') > 0) {
      toggleExample(snippets[i], setting['show-cs']);
    }
    else if (snippets[i].id.indexOf('-vb') > 0) {
      toggleExample(snippets[i], setting['show-vb']);
    }
  }
}


function toggleExample(ex, show) {
  if (show) {
    ex.removeAttribute("hidden");
  }
  else {
    ex.setAttribute("hidden", "hidden");
}

]]>
</script>

A working example of this code follows:

This book includes samples in both C# and VisualBasic. You can disable one or both languages from being displayed by checking the following options:

Sorry, this functionality is only available when both scripting and cookies are enabled.
public class HelloWorld {
   public static void Main() {
      System.Console.WriteLine("Hello, World!");
   }
}
Module HelloWorld
  Sub Main()
      MsgBox("Hello, World!")
  End Sub
End Module

Compliance References and Standards

Frequently Asked Questions

How come the EPUB Navigation Document uses the hidden attribute to hide content?

The EPUB Navigation Document is a special case. It is declarative markup intended for use by reading systems to create their own dynamic tables of contents, that happens to be written in XHTML. It is not intended to be rendered as plain old XHTML, except when embedded in the content of a publication (i.e., it facilitates two uses, but is not meant to be rendered the same way in both).

When rendered as XHTML, the hidden attribute will remove access to the hidden nodes from assistive technologies.