This page explores the accessibility and impacts of a number of techniques used to hide and minimize content in digital publications.
It is generally advised to avoid including hidden content that is only intended for users of
assistive technologies, however, except where the content is not central to understanding the
publication. Standard hyperlinks to text alternatives and declarative approaches to minimizing
content (e.g., the details element) are more broadly usable than
hidden content, as not everyone who can benefit from this content uses an assistive technology.
When content has to be selectively made to appear, ensure that progressive enhancement techniques are followed.
Table of Contents
HTML Techniques
-
HTML5 introduced the
hiddenattribute as a way to declaratively hide content (i.e., to hide content without relying on other technologies like CSS). When the attribute is set on an element, its content will not be rendered in any presentation, so will not be read by assistive technologies.The value of attribute has to be either an empty string, as in the previous example, or the value "
hidden" (hidden="hidden"). Although referred to as a "boolean" attribute, its value cannot be set to "true" or "false". To make content visible again, thehiddenattribute has to be removed from the element.The
hiddenattribute is most appropriate to author directly on an element when its content will never be made visible. (See the scripting section on dynamically setting the attribute if content will be toggled between visible and hidden states.)The
hiddenattribute is most commonly used with the ARIA attributes that do not require visible content, likearia-labelledbyandaria-describedby.The effect of setting this attribute is the equivalent of setting the CSS
displayproperty tonone. It is more reliable than CSS options in modern user agents, however, as not all user agents support CSS styling.*[hidden] { display: none; } - The
detailselement -
The
detailselement does not strictly meet the requirement of hiding content. What it does provide is the ability to collapse content down to just the label specified in thesummarytag. One advantage of the element is that it does not require scripting support, which is often lacking in EPUB reading systems, to expand and collapse the content.Example — Effect of the
detailselementThe following examples shows a collapsed
detailselement. Clicking on the label expands the content.Markup:
<details> <summary>Description</summary> <p>The first of the three gas giants is …</p> </details>Demo:
Description
The first of the three gas giants is …
It is not required that the content begin in a collapsed state. By adding the
openattribute, the content will initially be expanded (the attribute is also a boolean, like thehiddenattribute, so its value is either an empty string or the valueopen).Example — Expanded
detailselementMarkup:
<details open=""> <summary>Description</summary> <p>The first of the three gas giants is …</p> </details>Demo:
Description
The first of the three gas giants is …
A current limitation, however, is that reading systems do not always repaginate well when the element is expanded or collapsed. Expanding may force content below the element off the bottom of the current page, making it unavailable to sighted readers. The attribute is also not well supported in older browsers, including not at all in Internet Explorer versions, so requires a polyfill to work.
The
detailselement is commonly paired with thearia-detailsattribute to associate descriptions with elements.
CSS Techniques
Although CSS provides a number of approaches to hiding content visually, the primary problems with using it are that:
- CSS is not always supported and can often be disabled by users.
- Support for new properties often takes a long time to develop and many never get supported in older user agents.
- EPUB reading systems often supply their own styling, so author styles may be ignored or overridden.
As a result, there is no guarantee that styled content will be hidden from any users depending on the user agent they are using. HTML techniques are generally more reliable.
- Setting
displaytonone -
The
displayproperty is a widespread method used to visually hide content, as its origins go back much further than thehiddenattribute and it is more direct and easily manipulable than setting the height and width of elements. Setting thedisplaytononecauses the element it is carried on to be removed from visual display and the accessibility tree, so assistive technologies will not read the content.Example — Effect of no display
Markup:
.display-none { display: none; } <p>This is the visible text<span class="display-none"> and this is not</span>.</p>Demo:
This is the visible text and this is not.
Like with the
hiddenattribute, content that is hidden using thedisplayproperty can be accessed by ARIA attributes that accept hidden content. The same flaw that this approach hides useful information from users who do not use assistive technologies also applies, however. - Clipping
-
Clipping is a technique that reduces content to a single pixel so that visual users are not aware that that the additional content is present.
The advantage of clipping content instead of hiding it completely is that assistive technologies will read the clipped content, whereas they ignore content set or styled to be hidden.
The
clip-pathproperty is the primary property used to achieve this effect, but a number of others are also required (some as fallbacks), as depicted in the following example.Example — Effect of clipping
The
spancontaining the text "and this is not" will not be visible when the content is rendered, but the text will still be read by an assistive technology.Markup:
.clip { clip-path: inset(100%); clip: rect(1px, 1px, 1px, 1px); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; } <p>This is the visible text<span class="clip"> and this is not</span>.</p>Demo:
This is the visible text and this is not.
Note
The
clipproperty is now deprecated. It is included as a fallback for older browsers.While this technique works well in web browsers, support in EPUB reading systems is inconsistent. Support for the new
clip-pathproperty is not widespread, and neither is support for olderclipproperty as it requires absolute positioning. - Zero
heightandwidth -
Setting an element's
heightandwidthproperties to0is similar to the clipping technique, except that assistive technologies typically will not read the content of elements without any size dimensions.Example — Effect of zero height and width
Markup:
.zero-height-width { height: 0; width: 0; } <p>This is the visible text<span class="zero-height-width"> and this is not</span>.</p>Demo:
This is the visible text and this is not.
Even though setting an element's dimensions to zero does not remove the content from accessibility tree, assistive technologies are often optimized to ignore content styled this way (it is why the clipping technique only reduces the size to one pixel, for example). This behavior is not universal, however, so the content may be read in some cases.
- Transparent
opacity -
Setting the
opacityproperty of an element to0makes it completely transparent to users, but assistive technologies will still read the text.Example — Effect of full opacity
In the following example, the second paragraph has its opacity set to
0to make it transparent, but there is still space where it is located.Markup:
.transparent { opacity: 0; } <p>This paragraph appears.</p> <p class="transparent">While this one is made fully opaque.</p> <p>So there is space between.</p>Demo:
This paragraph appears.
While this one is made fully opaque.
So there is space between.
The primary issues with the use of
opacityare support in EPUB reading systems and that it leaves space where the opaque text is.Note
It is also possible to change the opacity of just the text of an element by setting the alpha channel to be transparent (e.g., using the
rgba()or#RRGGBBAAvalue syntax). Support for alpha channel values is also not widespread in EPUB, however. - Transformations
-
The
transformproperty provides two options for hiding content: one is to scale the element to zero, and the other is to translate it off screen. In both cases, assistive technologies will still read the text.Using the
scaletransform essentially shrinks the referenced element down until it occupies no space. It is similar in effect to setting the height and width to zero, except that the full space the element would occupy does not disappear when scaling.Example — Effect of scaling
In the following example, the second paragraph is scaled to zero, but the space it occupies remains. Click the button in the demo to toggle the scaling.
Markup:
.scale { transform: scale(0); } <p>This paragraph appears.</p> <p class="scale">While this one is scaled.</p> <p>So there is space between.</p>Demo:
This paragraph appears.
While this one is scaled.
So there is space between.
Using the
translatetransform is similar in effect to absolute positioning content off screen, except that the full space the element would occupy does not disappear. The value is thexandycoordinates of the translating vector.Example — Effect of translating
In the following example, the second paragraph is translated off screen using a an x-coordinate of
-9999pxand y-coordinate of0. The space the element occupies remains, however. Click the button in the demo to toggle the effect.Markup:
.translate { transform: translate(-9999px); } <p>This paragraph appears.</p> <p class="translate">While this one is translated off screen.</p> <p>So there is space between.</p>Demo:
This paragraph appears.
While this one is translated off screen.
So there is space between.
Similar to the
opacity, the primary issues with usingtransformis that such animations are not well supported in EPUB reading systems and they leave space where the transformed text originated. - Setting
visibilitytohidden -
The
visibilityproperty is not commonly used to hide content in digital publications, as unlike thedisplayproperty it leaves a space in the rendered content where the element would appear. The content is not read by assistive technologies, despite the visible space.Example — Effect of hidden visibility
In the following example, a space the length of the text " and this is not" occurs where the hidden
spanis. Click the button in the demo to toggle the visibility.Markup:
.vis-hidden { visibility: hidden; } <p>This is the visible text<span class="vis-hidden"> and this is not</span> but now with space.</p>Demo:
This is the visible text and this is not but now with space.
The property is more commonly used on the Web to avoid the other content on the page shifting around when an element is hidden or made visible (e.g., to prevent a page footer from being pulled up from the bottom of the page).
Similar to the
displayproperty, content hidden this way is hidden to assistive technologies unless it is referenced from an ARIA attribute that allows hidden content. - Absolute
position -
Absolute positioning content off-screen using the
positionproperty is another common Web practice to hide it visually while leaving it for assistive technologies to announce. As it is only the visual position of the content that changes, assistive technologies will still read the text.Example — Effect of absolute positioning
Markup:
.abs-position { position: absolute; left: -9999px; } <p>This paragraph appears.</p> <p class="abs-position">While this one is positioned off screen.</p> <p>But there is no space between.</p>Demo:
This paragraph appears.
While this one is positioned off screen.
But there is no space between.
Using absolute positioning to place content off-screen is very unreliable in EPUB reading systems, however. Absolute positioning of content is often disabled outside of fixed layout publications, as it complicates the rendering and paginating of reflowable content. As a result, the content may appear fixed in an unexpected position on the page, potentially obscuring the other content for visual readers.
- Negative
text-indent -
The
text-indentproperty is sometimes used to push content out of the visible area of the screen by giving it a large negative number. Using a large number allows the text to be rendered on a single line and not reach the visible area of the screen. The content is still read by assistive technologies, even though it is not visually present.Example — Effect of negative indenting
In the following example, the negative indent on the second paragraph forces it to be rendered off-screen, giving the appearance it is no longer there. Click the button in the demo to toggle the indent.
Markup:
.negative-indent { text-indent: -9999px; } <p>This paragraph appears.</p> <p class="negative-indent">While this one is pushed off screen.</p> <p>But the space the element occupied remains.</p>Demo:
This paragraph appears.
While this one is pushed off screen.
But the space the element occupied remains.
Even among CSS techniques, negative indents tends to be particularly unreliable. It has been noted that it can cause a large scrollbar to appear in browsers, for example, to allow users to reach the content (although this can be mitigated by setting the directionality). The more common issue with EPUB reading systems is that they ignore negative indents and other attempts to manipulate content outside the viewing area.
It also normally requires other tandem properties, like shrunken font sizes or changes to the element height, to collapse the white space that results from simply moving the first line back. These may not be well-supported in EPUB reading systems, either.
Note
A similar technique employing an indent of
100%to push the code off-screen in the other direction has also been suggested for browsers, but this will also fail in reading systems that prevent content from being positioned off-screen. - Matching
colorwith background -
Although it is possible to hide content by making the foreground color match the background, it is arguably the worst option available for EPUB content.
The problems with hiding content this way in EPUB include:
- Reading systems often apply their own foreground and background colors so that all publications have the same look and feel. As a result, there is no guarantee the text will actually be hidden.
- Similarly, reading systems often provide users the option to change their color preference for foreground and background text.
- Reading systems often offer multiple reading modes (e.g., night reading) that reset the foreground and background colors, which will reveal the text even if it is hidden by default.
A more common problem across any user agent is that this method of hiding only obscures the text. Like with changing the visibility, the area the text occupies is still visible.
Assistive technologies will read text hidden this way, though, as changing the color does not actually remove it.
Example — Effect of matching text with background
In the following example, both the
colorandbackground-colorproperties are set to white to obscure the text.Markup:
.color-match { color: rgb(255,255,255); background-color: rgb(255,255,255); } <p>This paragraph appears.</p> <p class="color-match">While this one is colored to be hidden.</p> <p>So there is space between.</p>Demo:
This paragraph appears.
While this one colored to be hidden.
So there is space between.
ARIA Techniques
Although ARIA does not influence the display of content, it contains a number of attributes that can be used both to hide content from, and make hidden content accessible to, assistive technologies.
- The
aria-describedbyattribute -
The
aria-describedbyattribute is commonly used to associate hidden descriptions with an element, although it is not required that the referenced element be hidden. The value of the attribute is the ID of the element that contains the description.Example — Associating a desciption with an image
Note that the value of the attribute is not a fragment identifier (i.e., it does not include a hash character (
#) at the start, as would be expected in a hyperlink).<img … aria-describedby="img-desc"/> <p id="img-desc" hidden="hidden">The infographic shows …</p>The
aria-describedbyattribute may reference more than one element if the description is broken up across elements.The problem with using
aria-describedbyto reference any content, hidden or not, is that it reduces that content to a simple text string (i.e., there is no way to effectively move through the description). Users of assistive technologies consequently have to listen to that entire string of text before they can move on, which can be a frustrating experience.The use of
aria-describedbywith hidden content also limits access to the description to users of assistive technologies when there will be many users who could benefit from access. - The
aria-detailsattribute -
The
aria-detailsattribute is similar to thearia-describedbyattribute in that both identify additional information about the content of an element, but there are a couple of key differences:- It is not intended to reference hidden content.
- It does not reduce the referenced content to a simple text string — users are able to navigate the structure of the referenced content.
The value of the
aria-detailsattribute is the ID of the element that contains the description. The attribute can reference only a single element.The attribute is commonly used to reference the collapsible
detailselement. This use makes it one of the best options for providing descriptions in as minimally obtrusive a manner as possible for all users.Note
The use of "details" in the element and attribute names is somewhat coincidental. The
aria-detailselement can refer to any element containing additional information.Example — Adding a description for an image
Note that the value of the attribute is not a fragment identifier (i.e., it does not include a hash character (
#) at the start, as would be expected in a hyperlink).<img src="dollars.jpg" alt="…" aria-details="dollar-desc"/> <details id="dollar-desc"> <summary>Description</summary> … </details> -
Despite its name, the
aria-hiddenattribute does not control the visual rendering of content. When set, it indicates that the designated content is not to be rendered by an assistive technology (i.e., it is not to be included in the accessibility tree).Unlike the
hiddenattribute, the value must be "true" or "false". An empty value (aria-hidden="") is the same as not specifying the attribute.The
aria-hiddenattribute should rarely be needed in digital publications. It is only of use if there is redundant or extraneous visual content, like pull quotes.Note that ARIA attributes that can reference hidden content (e.g.,
aria-describedbyandaria-labelledby) ignore this attribute — they will include the hidden text in their values. - The
aria-labelandaria-labelledbyattributes -
The
aria-labelandaria-labelledbyattribute both allow an accessible name to be provided for an element.aria-labelallows a hidden name to be specified.Example — Specifying a hidden name
<section aria-label="Explanation">The attribute is useful in digital publishing where only whitespace has been used to indicate new sections (e.g., headingless front matter sections, groups of index or bibliography entries). It is important that these sections be given a name, as without an explicit heading a
sectionwill not be navigable by assistive technology.The
aria-labelledbyattribute serves an identical purpose, but it allows the name to be included in another element (which can be hidden). The value of thearia-labelledbyattribute is the ID of the element that contains the name.Example — Specifying an visible name
Note that the value of the attribute is not a fragment identifier (i.e., it does not include a hash character (
#) at the start, as would be expected in a hyperlink).<div role="note" aria-labelledby="note-hd"> <p id="note-hd" class="hd">Warning!</p> … </div>The
aria-labelledbyattribute may reference more than one element if the label is split across multiple elements.It is not strictly necessary to use the
aria-labelledbyattribute when a section of content has an explicit heading.Example — Section with explicit heading
<section> <h2>Definitions</h2> … </section>Assistive technologies will associate the first heading element with the section. It can help with older browsers and assistive technologies to explicitly associate headings, however.
- The
presentationrole -
A common misconception is that adding the
presentationrole to an element is a way to hide content from assistive technologies. It is not!This misconception arises in part because this role is often applied to images that users do not need to encounter.
Example — Image used for visual spacing
<img src="spacer.href" alt="" role="presentation"/>In fact, it is the empty
altattribute that signals to assistive technologies that there is no content and the image can be safely ignored.Setting
role="presentation"on any element only removes its semantics. The content of the element is untouched.Note
The ARIA working group is moving to replace the
presentationrole withnoneto better reflect that it is the semantics of the element that are ignored, not the content.
Scripting Techniques
Although JavaScript does not provide any new abilities of its own to hide content, it allows
developers to manipulate a document to hide content using all of the techniques mentioned on this
page. Developers can dynamically add and remove the hidden attribute, for example, or
assign CSS classes to elements. And ARIA, of course, is designed to be modified by script.
Example — Setting attributes and classes
The following example shows how the hidden attribute can be added to an element
using the JavaScript setAttribute function and the class hide can
be added using classList.add.
/* set the hidden attribute */
document.getElementById('hideyho').setAttribute('hidden','');
/* set a css class */
document.getElementById('hideyho').classList.add('hide');
The one advantage that JavaScript has over using native techniques directly is that it allows for progressive enhancement when hiding content. There are times when content may need to be toggled on and off depending on user preference.
For example, a book on programming might include examples in multiple languages, allowing the user to selectively enable only the language they are most comfortable with. Using HTML or CSS techniques to hide one language by default could lead to those examples never being available to a user without scripting support (i.e., the scripts to toggle the choice will not work). By instead using JavaScript when the page loads, nothing will be hidden from users if scripting is not available; the scripting fails gracefully without loss of information.
Similarly, if the answers to questions in a textbook are only revealed using script, they will not be accessible to any users.
Example — Progressive enhancement
The following example uses the details element to hide the answer in reading
systems that do not support scripting. When scripting is supported, the details
element is hidden and a set of radio buttons are enabled instead, with a message about
whether the answer is correct or not being dynamically generated.
There are buttons after the demo to reset the question and toggle between the dynamic and static versions.
Markup:
<fieldset>
<label>Which of the following is a liquid?</label>
<ul class="q">
<li>
<input type="radio" name="q1-ans" value="a"
onclick="revealResult(true)" hidden="hidden">
A - Water
</li>
<li>
<input type="radio" name="q1-ans" value="b"
onclick="revealResult(false)" hidden="hidden">
B - Ice
</li>
<li>
<input type="radio" name="q1-ans" value="c"
onclick="revealResult(false)" hidden="hidden">
C - Steam
</li>
</ul>
<div id="q1-result" aria-live="assertive" hidden=""></div>
<details id="q1-static-ans">
<summary>Answer</summary>
<p>A - Water</p>
</details>
</fieldset>
<script>
document.onload = configureTest();
function configureTest() {
document.getElementById('q1-static-ans').classList.add('hidden');
document.getElementById('q1-result').removeAttribute('hidden');
var q1_ans = document.getElementsByName('q1-ans');
q1_ans.forEach( function(checkbox) {
checkbox.removeAttribute('hidden');
});
}
function revealResult(correct) {
var res_elem = document.getElementById('q1-result');
var result = correct ? 'Correct!' : 'Sorry, try again!';
res_elem.textContent = '';
res_elem.appendChild(document.createTextNode(result));
}
</script>
Demo:
Related Links
- MDN — <details>: The Details disclosure element
- MDN — hidden
- HTML — The
hiddenattribute - HTML — The
detailselement - WCAG 2.1 — Using CSS to hide a portion of the link text
- CSS — Clipping Shape: the clip-path property
- CSS — Content height: the 'height' property
- CSS — Content width: the 'width' property
- CSS — The 'display' property
- CSS — Visibility: the 'visibility' property
- CSS — Indentation: the 'text-indent' property
- CSS — Choosing a positioning scheme: 'position' property
- CSS — Transparency: the 'opacity' property
- CSS — The 'transform' Property
- CSS — Foreground color: the 'color' property
- ARIA — aria-hidden (state)
- ARIA — aria-describedby (property)
- ARIA — aria-details (property)
- ARIA — aria-label (property)
- ARIA — aria-labelledby (property)
- ARIA — presentation (role)